﻿//-----------------------------------------------------------------------
// <copyright company="Microsoft Corporation">
//     Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace Microsoft.DevDiv.Wpf.Samples.Controls
{
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Input;

    /// <summary>
    /// TextBox that raises a command when a certain key and/or modifier is pressed
    /// </summary>
    public class CommandTextBox : TextBox, ICommandSource
    {
        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandTextBox));

        public static readonly DependencyProperty CommandParameterProperty =
            DependencyProperty.Register("CommandParameter", typeof(object), typeof(CommandTextBox));

        public static readonly DependencyProperty CommandTargetProperty =
            DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(CommandTextBox));

        public static readonly DependencyProperty CommandKeyProperty =
            DependencyProperty.Register("CommandKey", typeof(Key), typeof(CommandTextBox), new PropertyMetadata(Key.Return));

        public static readonly DependencyProperty CommandModifierKeysProperty =
            DependencyProperty.Register("CommandModifierKeys", typeof(ModifierKeys), typeof(CommandTextBox), new PropertyMetadata(ModifierKeys.None));

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Justification = "No fields are initialized in static constructor")]
        static CommandTextBox()
        {
            FrameworkPropertyMetadata metaData = new FrameworkPropertyMetadata()
            {
                DefaultUpdateSourceTrigger = UpdateSourceTrigger.Explicit
            };

            TextBox.TextProperty.OverrideMetadata(typeof(CommandTextBox), metaData);
        }

        /// <summary>
        /// Command to raise
        /// </summary>
        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

        /// <summary>
        /// Parameter to raise commad with
        /// </summary>
        public object CommandParameter
        {
            get { return GetValue(CommandParameterProperty); }
            set { SetValue(CommandParameterProperty, value); }
        }

        /// <summary>
        /// Target of command
        /// </summary>
        public IInputElement CommandTarget
        {
            get { return (IInputElement)GetValue(CommandTargetProperty); }
            set { SetValue(CommandTargetProperty, value); }
        }

        /// <summary>
        /// Key to activate command
        /// </summary>
        public Key CommandKey
        {
            get { return (Key)GetValue(CommandKeyProperty); }
            set { SetValue(CommandKeyProperty, value); }
        }

        /// <summary>
        /// Modifier to activate command
        /// </summary>
        public ModifierKeys CommandModifierKeys
        {
            get { return (ModifierKeys)GetValue(CommandModifierKeysProperty); }
            set { SetValue(CommandModifierKeysProperty, value); }
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);

            ModifierKeys modifierKeys = this.CommandModifierKeys;
            if (e.Key == this.CommandKey && ((e.KeyboardDevice.Modifiers & modifierKeys) == modifierKeys))
            {
                BindingExpressionBase bindingExpression = BindingOperations.GetBindingExpressionBase(this, TextBox.TextProperty);
                if (bindingExpression != null)
                {
                    bindingExpression.UpdateSource();
                }

                e.Handled = e.Handled || CommandingOperations.ExecuteCommand(this, this);
            }
        }
    }
}